#include "process.h"
#include "schedule.h"
#include "pqueue.h"
#include "observer.h"

#include <stdlib.h>
#include <stdio.h>


struct pqueue *heap;

void stcp_init(void);
struct process *stcp_schedule(void);
int stcp_time_to_event(void);
void stcp_add(struct process *);
int stcp_done(void);
void stcp_die(char *);

/*By Jacob Eichers and Cliff Buchanan. Contains the functionality for the stcp
	algorithm*/

struct schedFuncTable stcpSchedTab =
{
	&stcp_init,
	&stcp_schedule,
	&stcp_time_to_event,
	&stcp_add,
	&stcp_done
};

void stcp_init()
{
	heap = pq_create();
	if (heap == NULL)
		{stcp_die("stcp_init");}
}

struct process *stcp_schedule()
{
	struct process *shortest;
	
	if (!pq_is_empty(heap))
	{
		shortest = pq_remove(heap);
		return shortest;
	}
	else
	{
		fprintf(stderr, "stcp_schedule: scheduler empty!\n");
		stcp_die("stcp_schedule");
		return NULL;
	}
}

int stcp_time_to_event()
{
	struct process *p;
	int t;

	if (!pq_is_empty(heap))
	{
		p = pq_peek(heap);
		t = (p->lifeTime)-(p->time);
		
		return t>=0 ? t : 0;
	}
	else
	{
		fprintf(stderr, "scheduler empty!\n");
		stcp_die("stcp_time_to_event");
		return -1;
	}
}

/* returns -1 if unsuccessful*/
void stcp_add (struct process *proc)
{
	if (proc != NULL)
	{
		int returnValue;
		
		returnValue = pq_insert(heap, proc);

		if (returnValue < 0)
		{
			perror("heapsize overflow! Exiting Program");
			exit(-1);
		}

	}

	obs_sched_add(proc);
}

int stcp_done()
{
	if(pq_is_empty(heap))
		{return 1;}
	else
		{return 0;}
}

void stcp_die(char *caller)
{
	fprintf(stderr, "%s: critical error! Exiting...\n", caller);
	exit(-1);
}
